from fastapi import APIRouter, Depends, HTTPException, status, Request, Response
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError

from datetime import timedelta

from ..schemas.auth import  Token
from ..services import SessionStore 
from ..services.auth import get_jwt_payload, authenticate_user, create_access_token, create_refresh_token

from scorpio.core.common import get_logger
logger=get_logger(__name__)

# 配置常量
ACCESS_TOKEN_EXPIRE_MINUTES = 30
REFRESH_TOKEN_EXPIRE_DAYS = 7

router = APIRouter(prefix="/auth", tags=["聊天接口"])
session_store = SessionStore()
oauth2_scheme = OAuth2PasswordBearer(
    tokenUrl="/auth/login", 
    auto_error=True
)

@router.post("/login", response_model=Token)
async def login(response: Response, form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
        )
    
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, 
        expires_delta=access_token_expires
    )
    
    refresh_token = create_refresh_token()
    # 存储刷新令牌
    session_store.set(
        key=f"refresh_token:{user.username}:{refresh_token}",
        value="valid",
        ttl=REFRESH_TOKEN_EXPIRE_DAYS * 24 * 60 * 60
    )
    logger.info("API auth/login headers",response.headers)
    
    # 设置HTTP-only Cookie
    response.set_cookie(
        key="access_token",
        value=access_token,
        httponly=True,
        secure=True,
        samesite="Lax",
        max_age=ACCESS_TOKEN_EXPIRE_MINUTES * 60
    )
    
    response.set_cookie(
        key="refresh_token",
        value=refresh_token,
        httponly=True,
        secure=True,
        samesite="Lax",
        max_age=REFRESH_TOKEN_EXPIRE_DAYS * 24 * 60 * 60
    )
    logger.info(f"access {access_token}, refresh {refresh_token}")
    return Token(
        access_token=access_token,
        token_type="bearer",
        refresh_token=refresh_token
    )
        

# 令牌刷新端点
@router.post("/refresh-token")
async def refresh_token(response: Response, refresh_token: str = Depends(oauth2_scheme)):
    try:
        # 在实际应用中应从cookie获取refresh_token
        username: str = get_jwt_payload(refresh_token).get("sub")
        if username is None:
            raise HTTPException(status_code=400, detail="Invalid token")
        
        # 检查刷新令牌有效性
        if not session_store.exists(f"refresh_token:{username}:{refresh_token}"):
            raise HTTPException(status_code=401, detail="Refresh token expired")
        
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")
    
    # 创建新访问令牌
    access_token = create_access_token(
        data={"sub": username}, 
        expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    )
    
    # 更新Cookie
    response.set_cookie(
        key="access_token",
        value=access_token,
        httponly=True,
        secure=True,
        samesite="Lax",
        max_age=ACCESS_TOKEN_EXPIRE_MINUTES * 60
    )
    
    return {"access_token": access_token}

# 受保护端点示例
@router.get("/protected")
async def protected_route(token: str = Depends(oauth2_scheme)):
    try:
        username: str = get_jwt_payload(token).get("sub")
        logger.info(f"token: {token}, username {username}")
        if username is None:
            raise HTTPException(status_code=401, detail="Invalid credentials")
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid credentials")
    
    return {"message": f"Hello {username}, you are authenticated"}

# 存储状态端点
@router.get("/storage-status")
async def storage_status():
    return {
        "storage_type": session_store.store_type,
        "description": "Current session storage engine"
    }

# 内存存储持久化端点
@router.post("/persist-memory-store")
async def persist_memory_store():
    if session_store.store_type == "memory":
        session_store.persist_to_disk()
        return {"message": "Memory store persisted to disk"}
    return {"message": "Not using memory store, persistence not needed"}

# 登出端点
@router.post("/logout")
async def logout(response: Response):
    # to-do: need to clear cookie from frontend
    # 清除Cookie

    response.delete_cookie("access_token")
    response.delete_cookie("refresh_token")
    return {"message": "Successfully logged out"}